#pragma once
#include <iostream>
#include <memory>
#include <sys/epoll.h>
//#include "Connection.hpp"
#include "Common.hpp"
#include "Socket.hpp"
#include "Channel.hpp"

using namespace SocketModule;
class Listener : public Connection{
public:
    Listener(int port)
    :_listenfd(std::make_unique<TcpSocket>(port))//初始化连接对象
    {
        _listenfd->BuildTcpServerSocketMethod(port);//一键构建套接字这一块
        SetEvent(EPOLLET | EPOLLIN);//设置连接文件描述符的关心事件,设为ET模式(事件每次到来只通知一次)以及监听读就绪
        SetNonBlock(_listenfd->Fd());//将文件描述符设置为非阻塞
    }
    void Recver() override
    {
        Inet_Addr client;
        //有连接到来
        while(true)//因为是ET模式所以一定要将所有连接读完,要想读完必定要多读一次,所以要让连接的文件描述符变为非阻塞,使得accept也是非阻塞
        {
            
            int sockfd = _listenfd -> Accept(&client);
            //std::cout << "hhhh" << std::endl;
            if(sockfd == ACCEPT_CONTINUE)//读取被打断
            {
                continue;
            }
            else if(sockfd == ACCEPT_DONE || sockfd == ACCEPT_ERR)//没有新的连接或者accept出错
            {
                
                break;
            }
            else
            {
                std::shared_ptr<Connection> conn = std::make_shared<Channel>(sockfd, client);//构建成一个套接字对象
                conn->SetEvent(EPOLLET | EPOLLIN);//设置该套接字文件描述符的事件
                if(_handler != nullptr)
                {
                    conn->SetFunction(_handler);//将回调方法注册给文件描述符
                }
                GetOwner()->AddConnection(conn);//利用回指指针将文件将套接字对象与容器关联
            }
        }
    }
    void Sender() override
    {
        ;
    }
    void Excepter() override final
    {
        ;
    }
    int GetSockFd() override
    {
        return _listenfd->Fd();//获取文件描述符
    }
    ~Listener()
    {

    }
private:
    std::unique_ptr<Socket> _listenfd;//连接fd对象
};